import sys
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout
from PyQt6.QtWebEngineWidgets import QWebEngineView
import folium
import io
import math

# 判断坐标是否在中国范围内
def out_of_china(lng, lat):
    return not (72.004 <= lng <= 137.8347 and 0.8293 <= lat <= 55.8271)

# 转换算法辅助函数
def transformlat(x, y):
    ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * math.sqrt(abs(x))
    ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(y * math.pi) + 40.0 * math.sin(y / 3.0 * math.pi)) * 2.0 / 3.0
    ret += (160.0 * math.sin(y / 12.0 * math.pi) + 320 * math.sin(y * math.pi / 30.0)) * 2.0 / 3.0
    return ret

# 转换算法辅助函数
def transformlng(x, y):
    ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * math.sqrt(abs(x))
    ret += (20.0 * math.sin(6.0 * x * math.pi) + 20.0 * math.sin(2.0 * x * math.pi)) * 2.0 / 3.0
    ret += (20.0 * math.sin(x * math.pi) + 40.0 * math.sin(x / 3.0 * math.pi)) * 2.0 / 3.0
    ret += (150.0 * math.sin(x / 12.0 * math.pi) + 300.0 * math.sin(x / 30.0 * math.pi)) * 2.0 / 3.0
    return ret

# WGS - 84 转 GCJ - 02
def wgs84_to_gcj02(lng, lat):
    if out_of_china(lng, lat):
        return [lng, lat]
    dlat = transformlat(lng - 105.0, lat - 35.0)
    dlng = transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * math.pi
    magic = math.sin(radlat)
    magic = 1 - 0.00669342162296594323 * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((6378245.0 * (1 - 0.00669342162296594323)) / (magic * sqrtmagic) * math.pi)
    dlng = (dlng * 180.0) / (6378245.0 / sqrtmagic * math.cos(radlat) * math.pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [mglng, mglat]

# GCJ - 02 转 WGS - 84
def gcj02_to_wgs84(lng, lat):
    if out_of_china(lng, lat):
        return [lng, lat]
    dlat = transformlat(lng - 105.0, lat - 35.0)
    dlng = transformlng(lng - 105.0, lat - 35.0)
    radlat = lat / 180.0 * math.pi
    magic = math.sin(radlat)
    magic = 1 - 0.00669342162296594323 * magic * magic
    sqrtmagic = math.sqrt(magic)
    dlat = (dlat * 180.0) / ((6378245.0 * (1 - 0.00669342162296594323)) / (magic * sqrtmagic) * math.pi)
    dlng = (dlng * 180.0) / (6378245.0 / sqrtmagic * math.cos(radlat) * math.pi)
    mglat = lat + dlat
    mglng = lng + dlng
    return [lng - (mglng - lng), lat - (mglat - lat)]


class MapWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        # 创建布局
        layout = QVBoxLayout()

        # 假设这是WGS - 84坐标
        wgs84_lng = 120.01
        wgs84_lat = 30.01
        # 转换为GCJ - 02坐标
        gcj02_lng, gcj02_lat = wgs84_to_gcj02(wgs84_lng, wgs84_lat)

        # 创建 folium 地图对象
        m = folium.Map(location=[gcj02_lat, gcj02_lng], zoom_start=12, control_scale=True, max_zoom=22)

        # 添加高德普通地图瓦片
        gaode_normal_tiles = folium.TileLayer(
            tiles='http://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}',
            attr='高德地图',
            subdomains='1234',
            max_zoom=19,
            name='高德普通地图'
        )
        gaode_normal_tiles.add_to(m)

        # 添加图层控制
        folium.LayerControl().add_to(m)

        # 保存地图为 HTML 文件
        data = io.BytesIO()
        m.save(data, close_file=False)
        html_content = data.getvalue().decode()

        # 修改 HTML 内容，添加模拟放大逻辑和 sessionStorage 拦截
        html_content = html_content.replace('</body>', """
        <script>
            // 拦截 sessionStorage 访问
            Object.defineProperty(window, 'sessionStorage', {
                get: function() {
                    return {
                        getItem: function() {},
                        setItem: function() {},
                        removeItem: function() {},
                        clear: function() {}
                    };
                }
            });

            // 全局变量，用于保存 Leaflet 地图对象
            var globalMap;

            // 监听 DOM 加载完成事件
            document.addEventListener('DOMContentLoaded', function() {
                // 每隔 100 毫秒检查 Leaflet 地图是否加载完成
                var checkLeaflet = setInterval(function() {
                    // 过滤出所有 Leaflet 地图对象
                    var maps = Object.values(window).filter(function(value) {
                        return value && value._initHooksCalled && value.getContainer;
                    });

                    // 如果找到地图对象，则清除定时器并绑定事件
                    if (maps.length > 0) {
                        clearInterval(checkLeaflet);
                        globalMap = maps[0];

                        // 修改瓦片加载行为，处理所有缩放级别
                        globalMap.eachLayer(function(layer) {
                            if (layer instanceof L.TileLayer) {
                                const maxAvailableZoom = 19; // 地图源最大可用缩放级别
                                layer.createTile = function(coords, done) {
                                    var tile = document.createElement('img');
                                    tile.onerror = L.bind(this._tileOnError, this, done, tile);
                                    tile.crossOrigin = '';

                                    var originalZ = coords.z;
                                    if (originalZ > maxAvailableZoom) {
                                        coords.z = maxAvailableZoom;
                                        var scaleFactor = Math.pow(2, originalZ - maxAvailableZoom);
                                        tile.style.transform = 'scale(' + scaleFactor + ')';
                                        tile.style.transformOrigin = '0 0';
                                    } else {
                                        // 对于小于等于最大可用缩放级别的缩放，正常加载瓦片
                                        coords.z = originalZ;
                                        tile.style.transform = 'scale(1)';
                                    }

                                    var url = this.getTileUrl(coords);
                                    tile.src = url;

                                    return tile;
                                };
                            }
                        });
                    }
                }, 100);
            });
        </script>
        </body>
        """)

        # 创建 QWebEngineView 并加载 HTML 内容
        self.web_view = QWebEngineView()
        self.web_view.setHtml(html_content)

        # 将 QWebEngineView 添加到布局中
        layout.addWidget(self.web_view)

        # 设置布局
        self.setLayout(layout)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    map_widget = MapWidget()
    map_widget.show()
    sys.exit(app.exec())

    